/*
 * @Author: zhangshu
 * @email: shiliang.zhang@tuya.com
 * @LastEditors: Please set LastEditors
 * @file name: app_mfg.c
 * @Description: 
 * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD
 * @Company: http://www.tuya.com
 * @Date: 2022-02-08
 * @LastEditTime: 2022-02-08
 */
#include "tal_mf_test.h"
#include "tal_memory.h"
#include "tal_sleep.h"

#include "app_common.h"
#include "app_mfg.h"
#include "app_led.h"
#include "app_gpio.h"

#include "app_battery.h"

// mf_test sensor type enum
typedef enum {
    DOOR_SENSOR = 0,    // door sensor:0x00
    PIR_SENSOR,         // pir motion sensor:0x01
    PHOTO_SENSOR,       // photo sensor:0x02
    SMOKE_SENSOR,       // smoke sensor:0x03
    GAS_SENSOR,         // gas sensor:0x04
    WATER_SENSOR,       // water sensor:0x05
    CO_SENSOR,          // CO sensor:0x06
    SOS_SENSOR          // SOS sensor:0x07
}OEM_SENSOR_TYPE_E;

//mfg test flag
STATIC UINT8_T mfg_test = MFG_TEST_NONE;
BOOL_T  mf_test_doing_flag = FALSE;
BOOL_T  sys_init_finish_flag = FALSE;

STATIC CHAR_T *itoa(INT_T num, CHAR_T *str, INT_T radix);

extern VOID_T app_oem_init(VOID_T);

/**
 * @description: manufactor test handler callback
 * @param[in] cmd: manufacture command, refer to TUYA_MF_TEST_CMD_T
 * @param[in] arg: callback data
 * @param[in] arg_len: data length
 * @return: TUYA_MF_TEST_RET_T, success when TUYA_MF_TEST_SUCCESS, or else
 */
TUYA_MF_TEST_RET_T tal_mf_test_handle_callback(TUYA_MF_TEST_CMD_T cmd,
                                                          UINT8_T*arg, 
                                                          UINT16_T arg_len)
{
    if (cmd == TUYA_MF_TRANSFER) {
        mfg_test = MFG_TEST_NONE;
    }
    switch (cmd) {
        //all leds start blink 
        case TUYA_MF_TEST_LED_BLINK_ALL: {
            mf_test_blink(TUYA_MF_TEST_LED_BLINK_ALL);
            break;
        }
        // button mf test
        case TUYA_MF_TEST_BUTTON: {
            break;
        }
        default :
          {
            //TAL_PR_TRACE("mf_test args0:%d\r\n",arg[0]);
            switch (arg[0])
            {
                // enter test
                case 0x00: {  
                    mfg_test = MFG_TEST_START;
                    mf_test_doing_flag = TRUE;
                    tal_cpu_force_wakeup();
                  break;
                }
                // led test
                case 0x08: {
                    app_oem_init();
                    app_led_preheat_init();
                    if(arg[1] == 0) {
                        mf_test_blink(TUYA_MF_TEST_LED_ON_ALL);
                    }
                    else if(arg[1] == 1) {
                        mf_test_blink(TUYA_MF_TEST_LED_OFF_ALL);
                    }
                    else if(arg[1] == 2) {
                        mfg_test = MFG_TEST_LED;
                        mf_test_blink(TUYA_MF_TEST_LED_BLINK_ALL);
                    }
                    break;
                }
                // key test
                case 0x0A: { 
                    app_oem_init();
                    mf_test_blink(TUYA_MF_TEST_LED_OFF_ALL);
                    mfg_test = MFG_TEST_NET_KEY;
                    return TUYA_MF_TEST_DOING;
                }
                case 0x0B: {  
                    app_oem_init();
                    app_gpio_preheat_init();
                    //TAL_PR_TRACE("mf_test args1:%d\r\n", arg[1]);
                    // sensor test
                    if (arg[1] == DOOR_SENSOR || arg[1] == PIR_SENSOR ||
                        arg[1] == SMOKE_SENSOR || arg[1] == GAS_SENSOR ||
                        arg[1] == WATER_SENSOR || arg[1] == CO_SENSOR) {
                        //TAL_PR_TRACE("start alarm test\r\n");
                        mfg_test = MFG_TEST_ALARM;
                        //tal_mf_test_bool_sensor_notify(DOOR_SENSOR, 0, TRUE); 
                        return TUYA_MF_TEST_DOING;
                    }
                }
                //battery test
                case 0x90: {
                    mfg_test = MFG_TEST_BATTERY;
                    app_oem_init();
                    app_battery_mf_test_start();
                    return TUYA_MF_TEST_DOING;
                }
                default:
                    break;
            }
            break;
        }
    }
    return TUYA_MF_TEST_SUCCESS;
}

/**
 * @description: key mfg test callback
 * @param[in] key_id: key id
 * @return: TRUE when test success or else
*/
BOOL_T mfg_key_test_callback(UINT32_T key_id)
{
    if (mfg_test != MFG_TEST_NET_KEY) {
        TAL_PR_TRACE("not net key mfg test\r\n");
        return FALSE;
    }
    mf_test_blink(TUYA_MF_TEST_LED_OFF_ALL);
    tal_mf_test_button_test_notify(key_id);
    return TRUE;
}

/**
 * @description: alarm1 mfg test callback
 * @param [in] {g_state} alarm gpio status
 * @return: TRUE when test success or else
 */
BOOL_T mfg_alarm1_test_callback(UINT8_T g_state)
{
    if (mfg_test != MFG_TEST_ALARM) {
        TAL_PR_TRACE("not alarm mfg test\r\n");
        return FALSE;
    }

    if(g_state) {
        tal_mf_test_bool_sensor_notify(DOOR_SENSOR, 0, TRUE); //TODO: select the suitable sensor type
    } else {
        tal_mf_test_bool_sensor_notify(DOOR_SENSOR, 0, FALSE);
    }
    return TRUE;
}

/**
 * @description: tamper mfg test callback
 * @param [in] {g_state} tamper gpio status
 * @return: TRUE when test success or else
 */
BOOL_T mfg_tamper_test_callback(UINT8_T g_state)
{
    if (mfg_test != MFG_TEST_TAMPER) {
        TAL_PR_TRACE("not tamper mfg test\r\n");
        return FALSE;
    }
    if (g_state) {
        tal_mf_test_bool_sensor_notify(0x07, 0x01, TRUE);
    } else {
        tal_mf_test_bool_sensor_notify(0x07, 0x01, FALSE);
    }
    return TRUE;
}

/**
 * @description: trouble mfg test callback
 * @param [in] {g_state} trouble gpio status
 * @return: TRUE when test success or else
 */
BOOL_T mfg_trouble_test_callback(UINT8_T g_state)
{
    if (mfg_test != MFG_TEST_TAMPER) {
        TAL_PR_TRACE("not trouble mfg test\r\n");
        return FALSE;
    }
    if (g_state) {
        tal_mf_test_bool_sensor_notify(0x07, 0x00, TRUE);
    } else {
        tal_mf_test_bool_sensor_notify(0x07, 0x00, FALSE);
    }
    return TRUE;
}

/**
 * @description: temperature humidity mfg test callback
 * @param [in] {temp_data} temperature data
 * @param [in] {humi_data} humidity data
 * @return: TRUE when test success or else
 */
BOOL_T mfg_temperature_humidity_test_callback(INT16_T temp_data, UINT16_T humi_data)
{
    if (mfg_test != MFG_TEST_TEMPERATURE_HUMIDITY) {
        TAL_PR_TRACE("not temperature humidity mfg test\r\n");
        return FALSE;
    }
    
    CHAR_T t_buff[30];
    // CHAR_T cmd = 0x0C;
    UINT8_T len = 0;

    tal_system_memset(t_buff, 0, SIZEOF(t_buff));
    len = tal_system_strlen((CHAR_T *)t_buff);
    //dev_mf_general_send(cmd, len, (UINT8_T *)t_buff);
    TAL_PR_TRACE("send mf data,cmd %d,len %d\r\n", 0x0C, len);
    t_buff[len] = '\0';
    TAL_PR_TRACE("%s\r\n", t_buff);
    return TRUE;
}

/**
* @description: illuminance mfg test callback
* @param [in] {lux_data} illuminance data
* @return: TRUE when test success or else
*/
BOOL_T mfg_illuminance_test_callback(UINT16_T lux_data)
{
    if (mfg_test != MFG_TEST_LIGHT_COLOR) {
        TAL_PR_TRACE("not light color mfg test\r\n");
        return FALSE;
    }

    UINT16_T lux_val = lux_data;

    UINT8_T v_ret_value[] = "{\"type\":\"luminance\",\"ch\":0,\"val\":2500}";

    char v_lux_ascii[6] = {0};
    UINT8_T v_len = 0;

    if (lux_val > 9999)
        lux_val = 9999;

    itoa(lux_val, v_lux_ascii, 10);
    v_len = tal_system_strlen(v_lux_ascii);

    tal_system_memcpy(&v_ret_value[33], v_lux_ascii, v_len);
    v_ret_value[33 + v_len] = '}';
    //暂不支持该接口，已反馈给OS
    //dev_mf_general_send(0x13, SIZEOF(v_ret_value) - 5 + v_len, v_ret_value);
    return TRUE;
}

/**
* @description: battery mf test callback
* @param [in] bt_val: battery sample voltage value.
* @return: TRUE when test success or else
*/
BOOL_T mfg_battery_test_callback(UINT16_T bt_val)
{
    if (mfg_test != MFG_TEST_BATTERY) {
        TAL_PR_TRACE("not battery mfg test\r\n");
        return FALSE;
    }

    UINT8_T report[] = {'{', '"', 'P', '"', ':', '1', ',', '"', 'B', '"', ':', '0', '0', '0', '0', '}'};

    UINT16_T voltage = bt_val;

    for (UINT8_T i = 0; i < 4; i++) {
        report[14 - i] = voltage % 10 + '0';
        voltage = voltage / 10;
    }

    tal_mf_test_general_send(0x90, sizeof(report), report);
    return TRUE;
}

/**
* @description: clear mfg flag
* @param[in] none
* @return: none
*/
VOID_T clear_mfg_test_flag(VOID_T)
{
    mfg_test = MFG_TEST_NONE;
}

/**
 * @description: get mfg test flag
 * @param[in] none
 * @return: none
*/
UINT8_T get_mfg_test(VOID_T)
{
  return mfg_test;
}

/**
* @description: itoa
* @param [in] num: char number
* @param [in] str: char string
* @param [in] radix:
* @return: char
*/
STATIC CHAR_T *itoa(INT_T num, CHAR_T *str, INT_T radix)
{
    char index[] = "0123456789ABCDEF";
    unsigned unum;
    int i = 0, j, k;
    if (radix == 10 && num < 0)
    {
        unum = (unsigned)-num;
        str[i++] = '-';
    }
    else
        unum = (unsigned)num;
    do
    {
        str[i++] = index[unum % (unsigned)radix];
        unum /= radix;
    } while (unum);
    str[i] = '\0';
    if (str[0] == '-')
        k = 1;
    else
        k = 0;

    for (j = k; j <= (i - 1) / 2; j++)
    {
        char temp;
        temp = str[j];
        str[j] = str[i - 1 + k - j];
        str[i - 1 + k - j] = temp;
    }
    return str;
}

